#include <smswatch.h>


const char* descriptorToStringL(const TDesC& aDescriptor)
	{
	TInt length = aDescriptor.Length();

	HBufC8* buffer = HBufC8::NewLC(length);
	buffer->Des().Copy(aDescriptor);

	char* str = new (ELeave) char[length + 1];
	Mem::Copy(str, buffer->Ptr(), length);
	str[length] = '\0';

	CleanupStack::PopAndDestroy(buffer);

	return str;
	}

void stringToDescriptor(const char* aString, TDes8& aDescriptor)
{
    TPtrC8 ptr(reinterpret_cast<const TUint8*>(aString));
    _LIT(KMyPanicDescriptor, "My panic text");
    __ASSERT_ALWAYS(User::StringLength(reinterpret_cast<const TUint8*>(aString))
 <= aDescriptor.MaxLength(), User::Panic(KMyPanicDescriptor, 0));
    aDescriptor.Copy(ptr);
}

void CPySmsSocketReaderObserver::MessageReceivedL(const TDesC& aMessage,
		const TDesC& aNumber)
	{
	RDebug::Print(_L("LOG: handling incoming message"));
#if PYTHON222
	PyEval_RestoreThread(PYTHON_TLS->thread_state);
#else
	PyGILState_STATE gstate = PyGILState_Ensure();
#endif	

	TInt error = KErrNone;
	PyObject *arglist;
	
	const char* msg = descriptorToStringL(aMessage);
	const char* num = descriptorToStringL(aNumber);
	
	arglist = Py_BuildValue("(s#s#)", msg, aMessage.Length(), num, aNumber.Length());

	PyObject* rval = PyEval_CallObject(iCb, arglist);

	if (!rval)
		{
		error = KErrPython;
		if (PyErr_Occurred() == PyExc_OSError)
			{
			PyObject *type, *value, *traceback;
			PyErr_Fetch(&type, &value, &traceback);
			if (PyInt_Check(value))
				error = PyInt_AS_LONG(value);
			Py_XDECREF(type)
;			Py_XDECREF(value);
			Py_XDECREF(traceback);
			}
		else
			{
			PyErr_Print();
			}
		}
	else
	Py_DECREF(rval);

#if PYTHON222
	PyEval_SaveThread();
#else
	PyGILState_Release(gstate);
#endif	

	}

void CPySmsSocketReaderObserver::HandleErrorL(const TInt aError,
		const TDesC& aErrorMessage)
	{
	RDebug::Print(_L("LOG: error"));
	}

//////////////TYPE METHODS////////////////////

/*
 * Deallocate inb.
 */
extern "C"
	{

	static void inb_dealloc(SMSENG_object *inbo)
		{
		if (inbo->inbox)
			{
			delete inbo->inbox;
			inbo->inbox = NULL;
			}
		PyObject_Del(inbo);
		}

	}

/*
 * Allocate inb.
 */
extern "C" PyObject *
new_inb_object(PyObject* /*self*/, PyObject *args)
	{
	RDebug::Print(_L("New SMSEngine object"));
	TInt error = KErrNone;

	SMSENG_object *inbo = PyObject_New(SMSENG_object, SMSENG_type);
	if (inbo == NULL)
		return PyErr_NoMemory();

	PyObject* c;

	if (!PyArg_ParseTuple(args, "O:set_callback", &c))
		return NULL;

	if (c == Py_None)
		c = NULL;
	else if (!PyCallable_Check(c))
		{
		PyErr_SetString(PyExc_TypeError, "callable expected");
		return NULL;
		}

	Py_XINCREF(c);
	CPySmsSocketReaderObserver* observer = new CPySmsSocketReaderObserver();
	observer->iCb = c;

	Py_BEGIN_ALLOW_THREADS
	TRAP(error, inbo->inbox = CSmsSocketReader::NewL(*observer));
	Py_END_ALLOW_THREADS

	if (inbo->inbox == NULL)
		{
		PyObject_Del(inbo);
		return PyErr_NoMemory();
		}

	if (error != KErrNone)
		{
		return SPyErr_SetFromSymbianOSErr(error);
		}

	return (PyObject*) inbo;
	}

/*
 * Delete message.
 */
extern "C" PyObject *
inb_start_listening(SMSENG_object* self, PyObject *args)
	{
	char* s = NULL;
	int lns;
	//Parse Python String Parameter to Symbian C++ char and than TPtrC8
	if (!PyArg_ParseTuple(args, "s#", &s, &lns))
		{
		return NULL;
		}

    HBufC8* matchTag = HBufC8::NewLC(lns);
    TPtr8 ptr = matchTag->Des();
	stringToDescriptor((const char *)s, ptr);
	TRAPD(error, self->inbox->StartListeningL(*matchTag))

	if (error != KErrNone)
		return SPyErr_SetFromSymbianOSErr(error);

	Py_INCREF(Py_None);
	return Py_None;
	}

extern "C" PyObject *
inb_stop_listening(SMSENG_object* self, PyObject *args)
	{
	self->inbox->StopListening();
	return Py_None;
	}

//////////////TYPE SET////////////////////////

extern "C"
	{

	static const PyMethodDef inb_methods[] =
		{
			{
			"start_listening", (PyCFunction) inb_start_listening, METH_VARARGS
			},
			{
			"stop_listening", (PyCFunction) inb_stop_listening, METH_VARARGS
			},
			{
			NULL, NULL
			} /* sentinel */
		};

	static PyObject *
	inb_getattr(SMSENG_object *op, char *name)
		{
		return Py_FindMethod((PyMethodDef*) inb_methods, (PyObject *) op, name);
		}

	static const PyTypeObject c_inb_type =
		{
		PyObject_HEAD_INIT(NULL)0, /*ob_size*/
		"smswatch.SMSEngine", /*tp_name*/
		sizeof(SMSENG_object), /*tp_basicsize*/
		0, /*tp_itemsize*/
		/* methods */
		(destructor)inb_dealloc, /*tp_dealloc*/
		0, /*tp_print*/
		(getattrfunc)inb_getattr, /*tp_getattr*/
		0, /*tp_setattr*/
		0, /*tp_compare*/
		0, /*tp_repr*/
		0, /*tp_as_number*/
		0, /*tp_as_sequence*/
		0, /*tp_as_mapping*/
		0, /*tp_hash*/
		};
	} /* extern "C" */

	//////////////INIT////////////////////////////

extern "C"
	{

	static const PyMethodDef inbox_methods[] =
		{
			{
			"SMSEngine", (PyCFunction) new_inb_object, METH_VARARGS, NULL
			},
			{
			NULL, NULL
			} /* sentinel */
		};

	DL_EXPORT(void) initsmswatch(void)
		{
		PyTypeObject* inb_type = PyObject_New(PyTypeObject, &PyType_Type);
		*inb_type = c_inb_type;
		inb_type->ob_type = &PyType_Type;

		SPyAddGlobalString("SMSENGType", (PyObject*) inb_type);

		PyObject *m, *d;

		m = Py_InitModule("smswatch", (PyMethodDef*)inbox_methods);
		d = PyModule_GetDict(m);
		}
	} /* extern "C" */

#ifndef EKA2
GLDEF_C TInt E32Dll(TDllReason)
	{
	return KErrNone;
	}
#endif
